/**
 * Created by Weizehua on 2017/1/29.
 */
import {HandlerClass, Handle, ParamType, Validators, Require} from "../Core/Dispatcher/Dispatcher";
import {RequestUserInfo} from "../Core/Dispatcher/Types";
import {MinLen, MaxLen} from "../Core/Validator/Length";
import {Connection} from "typeorm";
import {Album} from "./Album";
import {isLogged, isAdmin} from "../User/UserHandler";
import {VerifyUpload} from "../Core/Dispatcher/Shortcut";
import {DailyHeat, WeeklyHeat, MonthlyHeat} from "./AlbumsHeat";

@HandlerClass()
export class AlbumHandler {
    constructor(protected typeorm: Connection) {
    }

    @Handle('/album/new')
    @ParamType({
        title: String,
        uploadInfo: {url: String}
    })
    @Validators({
        title: [MinLen(2), MaxLen(10)],
    })
    @VerifyUpload()
    @Require(isLogged)
    async newAlbumHandler(userInfo: RequestUserInfo, param: any) {
        let title = param.title;
        let imageSource = param.uploadInfo.url || "";
        let album = new Album();
        album.user = <any>userInfo;
        album.title = title;
        album.imageSource = imageSource;
        album.dailyHeat = new DailyHeat();
        album.dailyHeat.album = album;
        album.weeklyHeat = new WeeklyHeat();
        album.weeklyHeat.album = album;
        album.monthlyHeat = new MonthlyHeat();
        album.monthlyHeat.album = album;

        album = await this.typeorm.entityManager.persist(album);
        return {
            success: true,
            album: {
                id: album.id,
                user: album.user,
                title: album.title,
                imageSource: album.imageSource
            }
        }
    }

    @Handle('/album/query/all')
    @Require(isLogged)
    async queryAllAlbumHandler(userInfo: RequestUserInfo) {
        let id = userInfo.id;
        let res = await this.typeorm.entityManager
            .createQueryBuilder(Album, 'album')
            .where('album.user = :user')
            .setParameters({user: userInfo.id})
            .getMany();
        return {
            success: true,
            albums: res
        }
    }

    static heatNameMapper = {'daily': 'daily', 'weekly': 'weekly', 'monthly': 'monthly'};
    static heatEntityMapper = {'daily': DailyHeat, 'weekly': WeeklyHeat, 'monthly': MonthlyHeat};

    @Handle('/album/heat/query')
    @ParamType({
        offset: Number,
        limit: Number,
        heatName: String,
    })
    @Validators({
        heatName: (val) => {
            return !!AlbumHandler.heatNameMapper
        }
    })
    @Require(isAdmin)
    async queryDailyHeatAlbumsHandler(param: any) {
        let offset = param.offset;
        let limit = param.limit;
        limit = Math.min(limit, 10);

        let res = await this.typeorm.getRepository(Album)
            .createQueryBuilder('album')
            .innerJoinAndSelect(`album.${AlbumHandler.heatNameMapper[param.heatName]}Heat`, 'heat')
            .orderBy('heat.heat')
            .setOffset(offset)
            .setLimit(limit)
            .getMany();
        return {
            success: true,
            albums: res
        }
    }

    @Handle('/album/tops/query')
    @ParamType({
        offset: Number,
        limit: Number,
        heatName: String,
    })
    @Validators({
        heatName: (val) => {
            return !!AlbumHandler.heatNameMapper
        }
    })
    @Require(isLogged)
    async queryDailyTopsAlbumsHandler(param: any) {
        let offset = param.offset;
        let limit = param.limit;
        limit = Math.min(limit, 10);
        let res = await this.typeorm.getRepository(Album)
            .createQueryBuilder('album')
            .innerJoinAndSelect(`album.${AlbumHandler.heatNameMapper[param.heatName]}Heat`, 'heat')
            .where('heat.isRecommended = true')
            .orderBy('heat.heat')
            .setOffset(offset)
            .setLimit(limit)
            .getMany();
        return {
            success: true,
            albums: res
        }
    }

    @Handle('/album/tops/recommend')
    @ParamType({
        id: Number,
        heatName: String,
    })
    @Validators({
        heatName: (val) => {
            return !!AlbumHandler.heatNameMapper
        }
    })
    @Require(isAdmin)
    async recommendDailyTopsAlbumHandler(param: any) {
        await this.typeorm.entityManager
            .createQueryBuilder(AlbumHandler.heatEntityMapper[param.heatName], 'heat')
            .update({isRecommended: true, recommendDate: new Date()})
            .where('heat.album = :album', {album: param.id})
            .execute();
        return {
            success: true,
        }
    }

    @Handle('/album/tops/unRecommend')
    @ParamType({
        id: Number,
        heatName: String,
    })
    @Validators({
        heatName: (val) => {
            return !!AlbumHandler.heatNameMapper
        }
    })
    @Require(isAdmin)
    async unRecommendDailyTopsAlbumHandler(param: any) {
        await this.typeorm.entityManager
            .createQueryBuilder(AlbumHandler.heatEntityMapper[param.heatName], 'heat')
            .update({isRecommended: true})
            .where('heat.album = :album', {album: param.id})
            .execute();
        return {
            success: true,
        }
    }
}
